package com.quiz.bis.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quiz.bis.domain.model.*;
import com.quiz.bis.domain.vo.*;
import com.quiz.bis.mapper.*;
import com.quiz.bis.service.IExamAutoGradeService;
import com.quiz.bis.service.IStudentActivityService;
import com.quiz.common.exception.ServiceException;
import com.quiz.common.mybatis.core.page.PageQuery;
import com.quiz.common.mybatis.core.page.TableDataInfo;
import com.quiz.common.utils.SecurityUtils;
import com.quiz.common.utils.StringUtils;
import com.quiz.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学生考试活动服务实现
 */
@Service
@RequiredArgsConstructor
public class StudentActivityServiceImpl implements IStudentActivityService {
    private final ExamMapper examMapper;
    private final ExamGroupMemberMapper groupMemberMapper;
    private final ExamParticipantMapper participantMapper;
    private final PaperQuestionMapper paperQuestionMapper;
    private final QuestionMapper questionMapper;
    private final QuestionTypeMapper questionTypeMapper;
    private final QuestionOptionMapper questionOptionMapper;
    private final ExamStudentRecordMapper recordMapper;
    private final PaperMapper paperMapper;
    private final SysUserMapper userMapper;
    private final IExamAutoGradeService autoGradeService;

    @Override
    @SuppressWarnings("all")
    public TableDataInfo<StudentActivityVo> pageActivityList(Long groupId, Integer type, Integer status, String searchKey, PageQuery pageQuery) {
        // 1. 验证学生是否属于该考试组
        Long userId = SecurityUtils.getUserId();
        boolean isMember = groupMemberMapper.exists(
                Wrappers.lambdaQuery(ExamGroupMember.class)
                        .eq(ExamGroupMember::getExamGroupId, groupId)
                        .eq(ExamGroupMember::getUserId, userId)
                        .eq(ExamGroupMember::getApproveStatus, 1) // 已通过审核
                        .eq(ExamGroupMember::getDelFlag, 0)
        );
        if (!isMember) {
            throw new ServiceException("您不属于该考试组，无法查看活动");
        }

        // 2. 查询活动列表
        Page<StudentActivityVo> page = examMapper.selectStudentActivityPage(pageQuery.build(),
                groupId,
                type,
                status, // status为空或非法注入为0时默认为1，保证只能查询已发布的数据
                userId,
                searchKey);

        // 3. 设置学生参与状态
        page.getRecords().forEach(vo -> setStudentParticipationStatus(vo, userId, Long.parseLong(vo.getId())));

        return TableDataInfo.build(page);
    }

    @Override
    public StudentActivityVo getActivityDetail(Long activityId) {
        // 1. 获取活动基本信息
        Exam exam = examMapper.selectOne(
                Wrappers.lambdaQuery(Exam.class)
                        .eq(Exam::getId, activityId)
                        .eq(Exam::getDelFlag, 0)
        );

        if (exam == null) {
            throw new ServiceException("活动不存在或已被删除");
        }

        // 2. 验证学生是否有权限查看
        Long userId = SecurityUtils.getUserId();
        boolean hasAccess = checkStudentAccess(exam.getExamGroupId(), userId);
        if (!hasAccess) {
            throw new ServiceException("您没有权限查看该活动");
        }

        // 3. 构建VO
        StudentActivityVo vo = new StudentActivityVo();
        vo.setId(exam.getId().toString());
        vo.setTitle(exam.getTitle());
        vo.setType(exam.getType());
        vo.setStartTime(exam.getStartTime());
        vo.setEndTime(exam.getEndTime());
        vo.setTimeLimit(exam.getTimeLimit());
        vo.setNeedIdentity(exam.getNeedIdentity());
        vo.setStatus(calculateActivityStatus(exam));
        vo.setConfigJson(exam.getConfigJson());

        // 设置试卷信息
        Paper paper = paperMapper.selectById(exam.getPaperId());
        if (paper != null) {
            vo.setPaperTotalScore(paper.getTotalScore());
            vo.setPaperPassScore(paper.getPassScore());
            vo.setPaperQuestionCount(paperQuestionMapper.selectCount(
                    Wrappers.lambdaQuery(PaperQuestion.class)
                            .eq(PaperQuestion::getPaperId, paper.getId())
                            .eq(PaperQuestion::getDelFlag, 0)
            ));
        }

        // 设置学生参与状态
        setStudentParticipationStatus(vo, userId, exam.getId());

        return vo;
    }

    @Override
    public StudentExamDetailVo getExamDetail(Long examId) {
        // 1. 获取考试信息
        Exam exam = examMapper.selectOne(
                Wrappers.lambdaQuery(Exam.class)
                        .eq(Exam::getId, examId)
                        .eq(Exam::getDelFlag, 0)
        );
        if (exam == null) {
            throw new ServiceException("考试不存在或已被删除");
        }

        // 2. 验证学生权限
        Long userId = SecurityUtils.getUserId();
        if (!checkStudentAccess(exam.getExamGroupId(), userId)) {
            throw new ServiceException("您没有权限参加此考试");
        }

        // 3. 获取试卷信息
        Paper paper = paperMapper.selectById(exam.getPaperId());
        if (paper == null) {
            throw new ServiceException("关联的试卷不存在");
        }

        // 4. 构建返回对象
        StudentExamDetailVo detailVo = new StudentExamDetailVo();
        detailVo.setExamId(exam.getId().toString());
        detailVo.setTitle(exam.getTitle());
        detailVo.setType(exam.getType());
        detailVo.setStartTime(exam.getStartTime());
        detailVo.setEndTime(exam.getEndTime());
        detailVo.setTimeLimit(exam.getTimeLimit());
        detailVo.setNeedIdentity(exam.getNeedIdentity());
        detailVo.setTotalScore(paper.getTotalScore());
        detailVo.setPassScore(paper.getPassScore());

        // 5. 获取试卷题目信息
        List<PaperQuestion> paperQuestions = paperQuestionMapper.selectList(
                Wrappers.lambdaQuery(PaperQuestion.class)
                        .eq(PaperQuestion::getPaperId, paper.getId())
                        .eq(PaperQuestion::getDelFlag, 0)
                        .orderByAsc(PaperQuestion::getSort)
        );

        // 6. 按题型分组
        Map<Long, List<PaperQuestion>> questionsByType = paperQuestions.stream()
                .collect(Collectors.groupingBy(pq -> {
                    Question question = questionMapper.selectById(pq.getQuestionId());
                    return question != null ? question.getTypeId() : null;
                }));

        // 7. 构建题型分类信息
        List<QuestionTypeVo> questionTypes = new ArrayList<>();
        questionsByType.forEach((typeId, pqList) -> {
            QuestionType questionType = questionTypeMapper.selectById(typeId);
            if (questionType != null) {
                QuestionTypeVo typeVo = new QuestionTypeVo();
                typeVo.setId(questionType.getId());
                typeVo.setName(questionType.getName());
                typeVo.setCount(pqList.size());
                typeVo.setScore(pqList.stream()
                        .map(PaperQuestion::getScore)
                        .reduce(BigDecimal.ZERO, BigDecimal::add));
                questionTypes.add(typeVo);
            }
        });
        detailVo.setQuestionTypes(questionTypes);

        // 8. 构建题目详情列表
        List<StudentQuestionVo> questions = new ArrayList<>();
        for (PaperQuestion paperQuestion : paperQuestions) {
            QuestionDetailVo questionDetailVo = questionMapper.selectQuestionById(paperQuestion.getQuestionId());
            if (questionDetailVo == null) {
                continue;
            }

            StudentQuestionVo questionVo = new StudentQuestionVo();
            questionVo.setId(questionDetailVo.getId());
            questionVo.setPaperQuestionId(paperQuestion.getId());
            questionVo.setType(questionDetailVo.getTypeId());
            questionVo.setTypeName(questionTypeMapper.selectById(questionDetailVo.getTypeId()).getName());
            questionVo.setContent(questionDetailVo.getContent());
            questionVo.setScore(paperQuestion.getScore());
            questionVo.setSort(paperQuestion.getSort());

            // 如果是选择题，获取选项
            if (questionDetailVo.getHasOption() != null && questionDetailVo.getHasOption() > 0) {
                List<QuestionOption> options = questionOptionMapper.selectList(
                        Wrappers.lambdaQuery(QuestionOption.class)
                                .eq(QuestionOption::getQuestionId, questionDetailVo.getId())
                                .eq(QuestionOption::getDelFlag, 0)
                                .orderByAsc(QuestionOption::getSort)
                );
                List<QuestionOptionVo> collect = options.stream()
                        .map(option -> new QuestionOptionVo(
                                option.getId(),
                                option.getOptionCode(),
                                option.getContent(),
                                option.getIsCorrect() == 1))
                        .collect(Collectors.toList());

                questionVo.setOptions(collect);

            }

            questions.add(questionVo);
        }
        detailVo.setQuestions(questions);

        // 9. 获取学生已有的作答记录
        ExamStudentRecord record = recordMapper.selectOne(
                Wrappers.lambdaQuery(ExamStudentRecord.class)
                        .eq(ExamStudentRecord::getExamId, examId)
                        .eq(ExamStudentRecord::getUserId, userId)
                        .eq(ExamStudentRecord::getDelFlag, 0)
        );
        if (record != null && StringUtils.isNotBlank(record.getAnswerJson())) {
            detailVo.setAnswers(record.getAnswerJson());
        }

        return detailVo;
    }

    @Override
    public boolean saveExamDraft(Long examId, String answersJson) {
        // 1. 验证考试是否存在
        Exam exam = examMapper.selectById(examId);
        if (exam == null || exam.getDelFlag() == 1) {
            throw new ServiceException("考试不存在或已被删除");
        }

        // 2. 验证学生权限
        Long userId = SecurityUtils.getUserId();
        if (!checkStudentAccess(exam.getExamGroupId(), userId)) {
            throw new ServiceException("您没有权限参加此考试");
        }

        // 3. 检查考试状态
        if (calculateActivityStatus(exam) != 2) {
            throw new ServiceException("考试不在进行中，无法保存答案");
        }

        // 4. 保存或更新作答记录
        ExamStudentRecord record = recordMapper.selectOne(
                Wrappers.lambdaQuery(ExamStudentRecord.class)
                        .eq(ExamStudentRecord::getExamId, examId)
                        .eq(ExamStudentRecord::getUserId, userId)
                        .eq(ExamStudentRecord::getDelFlag, 0)
        );

        if (record == null) {
            record = new ExamStudentRecord();
            record.setExamId(examId);
            record.setUserId(userId);
            record.setStartTime(new Date());
            record.setStatus(1); // 进行中
            record.setAnswerJson(answersJson);
            record.setCreateBy(SecurityUtils.getUsername());
            return recordMapper.insert(record) > 0;
        } else {
            record.setAnswerJson(answersJson);
            record.setUpdateBy(SecurityUtils.getUserId().toString());
            record.setUpdateTime(new Date());
            return recordMapper.updateById(record) > 0;
        }
    }

    @Override
    public boolean submitExam(Long examId, String answersJson) {
        // 1. 验证考试是否存在
        Exam exam = examMapper.selectById(examId);
        if (exam == null || exam.getDelFlag() == 1) {
            throw new ServiceException("考试不存在或已被删除");
        }

        // 2. 验证学生权限
        Long userId = SecurityUtils.getUserId();
        if (!checkStudentAccess(exam.getExamGroupId(), userId)) {
            throw new ServiceException("您没有权限参加此考试");
        }

        // 3. 检查考试状态
        int status = calculateActivityStatus(exam);
        if (status != 2 && status != 3) {
            throw new ServiceException("考试不在可提交状态");
        }

        // 4. 获取或创建作答记录
        ExamStudentRecord record = recordMapper.selectOne(
                Wrappers.lambdaQuery(ExamStudentRecord.class)
                        .eq(ExamStudentRecord::getExamId, examId)
                        .eq(ExamStudentRecord::getUserId, userId)
                        .eq(ExamStudentRecord::getDelFlag, 0)
        );

        if (record == null) {
            record = new ExamStudentRecord();
            record.setExamId(examId);
            record.setUserId(userId);
            record.setStartTime(new Date());
            record.setAnswerJson(answersJson);
            record.setCreateBy(SecurityUtils.getUsername());
        } else {
            record.setAnswerJson(answersJson);
            record.setUpdateBy(SecurityUtils.getUserId().toString());
            record.setUpdateTime(new Date());
        }

        // 5. 设置提交状态
        record.setSubmitTime(new Date());
        record.setStatus(status == 2 ? 2 : 3); // 2-已提交 3-超时提交

        // 6. 自动批改
        BigDecimal score = autoGradeService.start(exam, record.getId(), answersJson);
        record.setScore(score);

        // 7. 保存记录
        if (record.getId() == null) {
            return recordMapper.insert(record) > 0;
        } else {
            return recordMapper.updateById(record) > 0;
        }
    }


    /**
     * 计算活动状态
     */
    private int calculateActivityStatus(Exam exam) {
        if (exam.getStatus() != 1) {
            return 0; // 未发布
        }

        if (exam.getType() == 3) {
            return 1; // 作业只有发布状态
        }


        Date now = new Date();
        if (exam.getStartTime() == null || exam.getEndTime() == null) {
            return 1; // 未设置时间视为未开始
        }

        if (now.before(exam.getStartTime())) {
            return 1; // 未开始
        } else if (now.after(exam.getStartTime()) && now.before(exam.getEndTime())) {
            return 2; // 进行中
        } else {
            return 3; // 已结束
        }
    }

    /**
     * 检查学生是否有权限访问该活动
     */
    private boolean checkStudentAccess(Long groupId, Long userId) {
        // 1. 检查是否是考试组成员
        boolean isMember = groupMemberMapper.exists(
                Wrappers.lambdaQuery(ExamGroupMember.class)
                        .eq(ExamGroupMember::getExamGroupId, groupId)
                        .eq(ExamGroupMember::getUserId, userId)
                        .eq(ExamGroupMember::getApproveStatus, 1)
                        .eq(ExamGroupMember::getDelFlag, 0)
        );

        if (!isMember) {
            return false;
        }

        // 2. 检查是否在排除名单中
        ExamParticipant participant = participantMapper.selectOne(
                Wrappers.lambdaQuery(ExamParticipant.class)
                        .eq(ExamParticipant::getExamId, groupId)
        );

        if (participant != null && participant.getExcludedUserIds() != null) {
            List<Long> excludedUserIds = JSON.parseArray(participant.getExcludedUserIds(), Long.class);
            if (excludedUserIds.contains(userId)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 设置学生参与状态
     */
    private void setStudentParticipationStatus(StudentActivityVo vo, Long userId, Long examId) {
        ExamStudentRecord record = recordMapper.selectOne(
                Wrappers.lambdaQuery(ExamStudentRecord.class)
                        .eq(ExamStudentRecord::getExamId, examId)
                        .eq(ExamStudentRecord::getUserId, userId)
                        .eq(ExamStudentRecord::getDelFlag, 0)
        );

        if (record != null) {
            vo.setHasParticipated(true);
            vo.setParticipateStatus(record.getStatus());
            vo.setScore(record.getScore());
            vo.setSubmitTime(record.getSubmitTime());
        } else {
            vo.setHasParticipated(false);
        }
    }
}